// src/hooks/useServer.ts
import { ref, provide, inject } from 'vue';
import { io } from 'socket.io-client';
import { useUserStore } from '@/stores/userStore';
import { useRouter } from 'vue-router';

interface Message {
  id: string
  sender: string
  type: 'text' | 'functionTest'
  content: any
  timestamp: number
  route?: string
}

// 创建两个唯一的 Symbol 作为注入的 key
const WebSocketSymbol = Symbol('WebSocketConnection');

export const useServer = () => {
  const serverUrl = ref('http://localhost:5000/api');
  const wsserverUrl = ref('ws://localhost:5000');
  const router = useRouter();
  const userStore = useUserStore();
  
  // 使用 Map 来存储不同项目的 WebSocket 连接
  const wsConnections = ref<Map<string, ReturnType<typeof io>>>(new Map());
  const currentProjectToken = ref<string>('');
  const isConnected = ref<boolean>(false);
  const messages = ref<Message[]>([]);
  const messageRoute = ref<string>("");
  const audioRoute = ref<string>("");
  const mediaRecorder = ref<MediaRecorder | null>(null);
  const audioChunks = ref<Blob[]>([]);
  const isRecording = ref<boolean>(false);

  // 获取当前项目的 WebSocket 连接
  const getCurrentWs = () => {
    return currentProjectToken.value ? wsConnections.value.get(currentProjectToken.value) : null;
  };


  // 发送 GET 请求
  const get = async (endpoint: string, params?: Record<string, any>) => {
    try {
      const queryParams = params ? `?${new URLSearchParams(params).toString()}` : '';
      const response = await fetch(`${serverUrl.value}/${endpoint}${queryParams}`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },
      });
      if (!response.ok) throw new Error(`Error: ${response.status}`);
      return await response.json();
    } catch (error) {
      console.error('GET Request Error:', error);
      throw error;
    }
  };

  // 发送 POST 请求
  const post = async (endpoint: string, data: Record<string, any>) => {
    // 对于登录和注册请求，跳过用户验证
    const isAuthEndpoint = endpoint === 'login' || endpoint === 'register';
    
    // 检查用户是否登录（非登录/注册请求时）
    if (!isAuthEndpoint && !userStore.isLoggedIn) {
      router.push('/login');
      throw new Error('User not logged in');
    }

    try {
      const response = await fetch(`${serverUrl.value}/${endpoint}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
        body: JSON.stringify(
          isAuthEndpoint ? data : {
            ...data,
            userID: userStore.currentUser
          }
        ),
      });
      
      if (!response.ok) {
        // 如果是未授权错误或会话过期，跳转到登录页面
        if (response.status === 401 || response.status === 403) {
          userStore.logout();  // 清除本地登录状态
          router.push('/login');
          throw new Error('Session expired or unauthorized');
        }
        throw new Error(`Error: ${response.status}`);
      }
      
      return await response.json();
    } catch (error: any) {  // 明确指定 error 类型为 any
      console.error('POST Request Error:', error);
      // 如果错误消息包含特定关键词，也跳转到登录页面
      if (typeof error.message === 'string' && (
          error.message.toLowerCase().includes('unauthorized') || 
          error.message.toLowerCase().includes('unauthenticated') ||
          error.message.toLowerCase().includes('session'))) {
        userStore.logout();  // 清除本地登录状态
        router.push('/login');
      }
      throw error;
    }
  };

  const postWithCallback = async (
    endpoint: string,
    data: Record<string, any>,
    callback: (response: any) => void
  ) => {
    try {
      const response = await post(endpoint, data);
      callback(response); // 调用回调函数并传递响应数据
      return response; // 返回响应数据（可选）
    } catch (error) {
      console.error('POST Request with Callback Error:', error);
      throw error;
    }
  };

  // 连接到 Message WebSocket 服务器
  const connectWebSocket = (token: string) => {
    if (wsConnections.value.has(token)) {
      const existingWs = wsConnections.value.get(token);
      if (existingWs) {
        existingWs.close();
      }
    }

    // 创建新的连接
    const newWs = io(wsserverUrl.value + token);
    wsConnections.value.set(token, newWs);
    currentProjectToken.value = token;

    // 提供当前项目的 WebSocket 连接给子组件
    provide(WebSocketSymbol, newWs);

    newWs.on('connect', () => {
      console.log(`Connected to WebSocket for project ${token}`);
      isConnected.value = true;
    });
    newWs.on('disconnect', () => {
      console.log(`Disconnected from WebSocket for project ${token}`);
      isConnected.value = false;
    });
    


    
    newWs.on('toolExecuteTest', (data: any) => {
      console.log('Received toolExecuteTest:', data)
      messages.value.push({
        id: generateUniqueId(),
        sender: 'Server',
        type: 'functionTest',
        content: data,
        timestamp: Date.now(),
        route: "toolExecuteTest"
      })
    });
  };

const selectMessageRoute=(route:string)=>{
  messageRoute.value = route;
  getCurrentWs().on(route, (data:any) => {
    console.log('Received data: ', data);
    messages.value.push({
      id: generateUniqueId(),
      sender: 'Server',
      type: 'text',
      content: data,
      timestamp: Date.now(),
      route:messageRoute.value
    })
  });
}
const selectAudioRoute=(route:string)=>{
  audioRoute.value =route;
  startAudioRecording();
}

const startAudioRecording = async () => {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ 
      audio: {
        sampleRate: 16000,
        channelCount: 1,
        echoCancellation: true,
        noiseSuppression: true
      }
    });
    
    const audioContext = new AudioContext({
      sampleRate: 16000
    });
    
    // Load the AudioWorklet
    await audioContext.audioWorklet.addModule('/src/components/ts/audio-processor.js');
    
    const source = audioContext.createMediaStreamSource(stream);
    const workletNode = new AudioWorkletNode(audioContext, 'audio-processor');
    let audioChunks: Float32Array[] = [];
    
    workletNode.port.onmessage = (e) => {
      audioChunks.push(new Float32Array(e.data));
      
      if (audioChunks.length >= 4) {
        const wavData = convertToWav(audioChunks, 16000);
        const audioMessage = {
          type: 'audio',
          data: wavData,
          timestamp: Date.now()
        };
        sendAudioDataInRoute(audioRoute.value, audioMessage);
        audioChunks = [];
      }
    };
    
    source.connect(workletNode);
    workletNode.connect(audioContext.destination);
    
    mediaRecorder.value = {
      stop: () => {
        source.disconnect();
        workletNode.disconnect();
        stream.getTracks().forEach(track => track.stop());
        audioContext.close();
      }
    } as MediaRecorder;
    
    isRecording.value = true;
  } catch (error) {
    console.error('Error starting audio recording:', error);
  }
};

// 将Float32Array数组转换为WAV格式
const convertToWav = (audioData: Float32Array[], sampleRate: number): string => {
  const numChannels = 1;
  const format = 1; // PCM
  const bitDepth = 16;
  
  // 计算总长度
  let totalLength = 0;
  audioData.forEach(buffer => {
    totalLength += buffer.length;
  });
  
  // 创建ArrayBuffer
  const buffer = new ArrayBuffer(44 + totalLength * 2);
  const view = new DataView(buffer);
  
  // 写入WAV头部
  writeString(view, 0, 'RIFF');                      // RIFF标识
  view.setUint32(4, 36 + totalLength * 2, true);    // 文件长度
  writeString(view, 8, 'WAVE');                      // WAVE标识
  writeString(view, 12, 'fmt ');                     // fmt标识
  view.setUint32(16, 16, true);                     // fmt块长度
  view.setUint16(20, format, true);                 // 格式类型
  view.setUint16(22, numChannels, true);            // 声道数
  view.setUint32(24, sampleRate, true);             // 采样率
  view.setUint32(28, sampleRate * numChannels * bitDepth / 8, true); // 字节率
  view.setUint16(32, numChannels * bitDepth / 8, true); // 块对齐
  view.setUint16(34, bitDepth, true);               // 位深度
  writeString(view, 36, 'data');                     // data标识
  view.setUint32(40, totalLength * 2, true);        // 数据长度
  
  // 写入音频数据
  let offset = 44;
  audioData.forEach(buffer => {
    for (let i = 0; i < buffer.length; i++) {
      const s = Math.max(-1, Math.min(1, buffer[i]));
      view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
      offset += 2;
    }
  });
  
  // 转换为base64
  const uint8Array = new Uint8Array(buffer);
  let binary = '';
  for (let i = 0; i < uint8Array.length; i++) {
    binary += String.fromCharCode(uint8Array[i]);
  }
  const base64 = btoa(binary);
  return `data:audio/wav;base64,${base64}`;
};

// 辅助函数：写入字符串到DataView
const writeString = (view: DataView, offset: number, string: string) => {
  for (let i = 0; i < string.length; i++) {
    view.setUint8(offset + i, string.charCodeAt(i));
  }
};

const stopAudioRecording = () => {
  if (mediaRecorder.value && isRecording.value) {
    mediaRecorder.value.stop();
    isRecording.value = false;
  }
};

  // 发送消息到当前项目的 WebSocket 服务器
  const sendMessage = (message: string) => {
    const currentWs = getCurrentWs();
    if (currentWs && isConnected.value) {
      currentWs.emit(messageRoute.value, message);
      console.log('Message sent:', message);
    } else {
      console.error('WebSocket is not connected');
    }
  };

  const sendDataInRoute = (route: string, data: any) => {
    const currentWs = getCurrentWs();
    if (currentWs && isConnected.value) {
      currentWs.emit(route, data);
    }
  }

  const sendAudioDataInRoute = (route: string, data: any) => {
    const currentAudioWs = getCurrentWs();
    if (currentAudioWs ) {
      currentAudioWs.emit(route, data);
    }
  }

  // 关闭指定项目的 WebSocket 连接
  const closeWebSocket = (projectId?: string) => {
    const targetProjectId = projectId || currentProjectToken.value;
    if (targetProjectId) {
      const ws = wsConnections.value.get(targetProjectId);
      if (ws) {
        ws.close();
        wsConnections.value.delete(targetProjectId);
        console.log(`WebSocket connection closed for project ${targetProjectId}`);
      }
    }
  };


  // 切换到另一个项目的 WebSocket 连接
  const switchProject = (projectId: string) => {
    if (wsConnections.value.has(projectId)) {
      currentProjectToken.value = projectId;
      const ws = wsConnections.value.get(projectId);
      if (ws) {
        provide(WebSocketSymbol, ws);
        isConnected.value = ws.connected;
      }

    }
  };

  return { 
    serverUrl, 
    get, 
    post, 
    postWithCallback,
    ws: getCurrentWs,
    isConnected,
    messages, 
    connectWebSocket,
    sendMessage, 
    closeWebSocket,
    switchProject,
    currentProjectToken,
    sendDataInRoute,
    sendAudioDataInRoute,
    selectMessageRoute,
    selectAudioRoute,
    startAudioRecording,
    stopAudioRecording,
    isRecording
  };
};

function generateUniqueId(): string {
  return Math.random().toString(36).substring(2, 9);
}

export default useServer;